using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Net.Http.Headers;

namespace RBAC.Read.Api.Controllers
{
    /// <summary>
    /// 通用文件预览与下载（支持公开 URL 或 MinIO bucket/objectName 路径）
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class FileController : ControllerBase
    {
        private readonly IConfiguration _config;

        public FileController(IConfiguration config)
        {
            _config = config;
        }

        /// <summary>
        /// 预览（重定向到公共地址，浏览器自行处理展示）
        /// </summary>
        /// <param name="path">完整 http(s) 链接，或形如 bucket/objectName 的存储路径</param>
        [HttpGet]
        public IActionResult Preview([FromQuery] string path)
        {
            if (string.IsNullOrWhiteSpace(path)) return BadRequest("path is required");
            var url = BuildPublicUrl(path);
            return Redirect(url);
        }

        /// <summary>
        /// 下载（通过后端代理，设置文件名与 Content-Type）
        /// </summary>
        /// <param name="path">完整 http(s) 链接，或形如 bucket/objectName 的存储路径</param>
        /// <param name="fileName">下载文件名（可选，不传则从路径推断）</param>
        [HttpGet]
        public async Task<IActionResult> Download([FromQuery] string path, [FromQuery] string? fileName)
        {
            if (string.IsNullOrWhiteSpace(path)) return BadRequest("path is required");
            var url = BuildPublicUrl(path);

            using var http = new HttpClient();
            using var resp = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
            if (!resp.IsSuccessStatusCode)
            {
                return StatusCode((int)resp.StatusCode, $"fetch failed: {(int)resp.StatusCode}");
            }

            var ct = resp.Content.Headers.ContentType?.ToString() ?? "application/octet-stream";
            var guessedName = string.IsNullOrWhiteSpace(fileName) ? GuessFileNameFromPath(path) : fileName!;

            // 将远端流拉到内存（若后续存在大文件，可改为 FileStreamResult+管道转发）
            var bytes = await resp.Content.ReadAsByteArrayAsync();
            return File(bytes, ct, guessedName);
        }

        private string BuildPublicUrl(string path)
        {
            if (path.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || path.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
            {
                return path;
            }
            // path 形如 bucket/objectName
            var endpoint = _config["Minio:PublicEndpoint"] ?? _config["Minio:Endpoint"] ?? "localhost:9000";
            var scheme = _config["Minio:Scheme"] ?? "http";
            var trimmed = path.TrimStart('/');
            return $"{scheme}://{endpoint}/{trimmed}";
        }

        private static string GuessFileNameFromPath(string path)
        {
            try
            {
                // 对于完整 URL
                if (Uri.TryCreate(path, UriKind.Absolute, out var uri))
                {
                    var last = uri.Segments.LastOrDefault()?.Trim('/') ?? "file";
                    return Uri.UnescapeDataString(last);
                }
                // 对于 bucket/objectName
                var idx = path.LastIndexOf('/');
                return idx >= 0 ? path.Substring(idx + 1) : path;
            }
            catch
            {
                return "file";
            }
        }
    }
}
